package com.biz.hunter.wechat;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.biz.hunter.dao.CityDAO;
import com.biz.hunter.dao.CompanyDAO;
import com.biz.hunter.dao.EmployeeDAO;
import com.biz.hunter.dao.PageDAO;
import com.biz.hunter.dao.UserDAO;
import com.biz.hunter.db.entity.City;
import com.biz.hunter.db.entity.Company;
import com.biz.hunter.db.entity.Employee;
import com.biz.hunter.db.entity.JobDesc;
import com.biz.hunter.db.entity.Page;
import com.biz.hunter.db.entity.PathEnum;
import com.biz.hunter.db.entity.PlatformEnum;
import com.biz.hunter.db.entity.UserInfo;
import com.biz.hunter.service.IJobDescService;
import com.biz.hunter.service.impl.JobDescService;
import com.biz.hunter.webchat.controller.SysConfigRepo;
import com.biz.system.config.SystemConfig;
import com.biz.system.config.WebchatServiceConstant;
import com.biz.wechat.api.media.Article;
import com.biz.wechat.api.msg.MessageUtil;
import com.biz.wechat.api.msg.resp.ResponseNewsMessage;
import com.biz.wechat.api.msg.resp.ResponseTextMessage;
import com.biz.wechat.util.CookieUtil;
import com.biz.wechat.util.SignUtil;

@Controller
public class WebchatMainController {
	private static final Logger logger = LoggerFactory
			.getLogger(WebchatMainController.class);
	@Autowired
	private CityDAO cityDAO;
	@Autowired
	private CompanyDAO companyDAO;

	@Autowired
	private UserDAO userDAO;

	@Autowired
	private EmployeeDAO employeeDAO;

	@Autowired
	private PageDAO pageDAO;

	@Autowired
	private IJobDescService jobService;

	@Autowired
	private SysConfigRepo sysConfigDAO;

	@RequestMapping(value = "/WebChatMainService", method = RequestMethod.GET)
	public @ResponseBody String checkSignature(
			@RequestParam(value = "signature") String signature,
			@RequestParam(value = "timestamp") String timestamp,
			@RequestParam(value = "nonce") String nonce,
			@RequestParam(value = "echostr") String echostr) {
		String str = "";
		if (signature != null && timestamp != null && nonce != null
				&& echostr != null) {
			if (SignUtil.checkSignature(signature,
					WebchatServiceConstant.TOKEN, timestamp, nonce)) {
				str = echostr;
			}
		} else {
			str = "Sorry!";
		}

		logger.debug("return echostr is " + str);
		return str;
	}

	/**
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/WebChatMainService", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
	public @ResponseBody String doPost(HttpServletRequest request,
			HttpServletResponse response) {
		// 解析XML消息
		Map<String, String> requestMap = MessageUtil.parseXml(request);
		if (CollectionUtils.isEmpty(requestMap)) {
			logger.error("the input request Map is empty");
			return "";
		}

		String fromUserName = requestMap.get("FromUserName");
		// TODO: save cookie
		String openid = CookieUtil.getOpenid(request);
		logger.info("before refresh, cookie is" + openid);
//		CookieUtil.setOpenid(response, "/demo/",fromUserName);
		//CookieUtil.setOpenid(response,request.getContextPath(),fromUserName); 
		CookieUtil.setOpenid(response,fromUserName); 
		logger.info("refresh the client openid: " + fromUserName);
		// 进入消息/事件处理逻辑
		String respMessage = processRequest(requestMap);
//		CookieUtil.setOpenid(response,"/demo/",fromUserName);
		return respMessage;
	}

	public String processRequest(Map<String, String> requestMap) {
		String respMessage = "";

		String respContent = "请求处理异常，请稍候尝试！";

		String fromUserName = requestMap.get("FromUserName");
		String toUserName = requestMap.get("ToUserName");
		String msgType = requestMap.get("MsgType");

		respMessage = buildTextMsg(fromUserName, toUserName, respContent);

		if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {

			String rsqContent = requestMap.get("Content");
			logger.debug("text msg is" + rsqContent);

			respMessage = processTextMessage(fromUserName, toUserName,
					rsqContent);

		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
			respContent = "您发送的是图片消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
			respContent = "您发送的是地理位置消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
			respContent = "您发送的是链接消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
			respContent = "您发送的是视频消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
			if (requestMap.get("Recognition") != null) {
				respContent = "您发送的是语音识别后的消息！";
			} else {
				respContent = "您发送的是音频消息！";
			}
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
			String eventType = requestMap.get("Event");
			if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
				respMessage = subscribe(respMessage, fromUserName, toUserName);

			} else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {

				unsubscribe(fromUserName);
				// respContent = "谢谢您取消关注！";

			} else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
				logger.warn("暂不支持SCAN");
				// respMessage = transferMsg(fromUserName, toUserName);

			} else if (eventType.equals(MessageUtil.EVENT_TYPE_GEO)) {
				logger.warn("暂不支持地理位置");
			} else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
				String eventKey = requestMap.get("EventKey");
				logger.debug("the menu click key is " + eventKey);
				if (eventKey.equalsIgnoreCase("niuren")) {
					// respMessage = buildNewsMsg(fromUserName, toUserName,
					// PathEnum.recommend);
//					respContent = "欢迎加入人才库,请先点击以下链接进行注册\n "
//							+ "<a href ='http://www.tiaonali.com/demo/wechat/candidate/main.page?openId="
//							+ fromUserName + "'>牛人注册</a>";
					
					respMessage = buildTextMsg(fromUserName, toUserName,
							respContent);
				}
				if (eventKey.equalsIgnoreCase("job")) {
					logger.debug("send out wodezhiwei");

					// respMessage = buildNewsMsg(fromUserName, toUserName,
					// PathEnum.assistant);
				}
				if (eventKey.equalsIgnoreCase("wentifankui")) {
					respMessage = buildTextMsg(fromUserName, toUserName,
							"请切换到键盘输入，直接给我们发微信，我们的客服会通过微信为您服务。");
				}
			}
		}
		return respMessage;
	}

	private void unsubscribe(String fromUserName) {
		int result = userDAO.unSubscribe(fromUserName);
		Employee em = employeeDAO.getByOpenId(fromUserName);
		if (em == null) {
			logger.info("there is no employee registed.");
			return;
		}
		em.setActive(Employee.inactivate);
		result = employeeDAO.update(em);

		logger.debug("unsubscribe() return value is " + result);
	}

	private String subscribe(String respMessage, String fromUserName,
			String toUserName) {
		String respContent;
		UserInfo userInfo = null;
		try {
			// String token = sysConfigDAO.getAccessToken();
			// userInfo = userDAO.subscribe(fromUserName, token);
			// Employee em = employeeDAO.getByOpenId(fromUserName,
			// Employee.inactivate);
			// if (em != null) {
			// logger.info("employee not null, activate it" + fromUserName);
			// em.setActive(Employee.activate);
			// employeeDAO.update(em);
			// }

			userInfo = userDAO.getByOpenId(fromUserName);
			if (userInfo == null) {
				userInfo = new UserInfo();
				userInfo.setSubscribe_time(System.currentTimeMillis());
				userInfo.setOpenid(fromUserName);
				userInfo.setSubscribe(1);
				int insertId = userDAO.saveOpenId(userInfo);
				logger.info("save subscriber info. new userId is "+ insertId);
			}
			
			
		} catch (Exception e) {
			logger.error("subscribe and insert userinfo into DB", e);
		}
		if (userInfo != null) {

//			respContent = convertWelcomeMsg(fromUserName,
//					userInfo.getNickname());
			respMessage = buildTextMsg(fromUserName, toUserName, "欢迎您的关注");
		} else {
			logger.error("DAO insert Userinfo failed. ");
		}
		return respMessage;
	}

	/**
	 * 如果是已填写直通车的用户，查看用户的关注公司和现任职位， 找到10条相关职位，推送图文新闻ResponseNewsMessage
	 * 
	 * @param fromUserName
	 * @param toUserName
	 * @param rsqContent
	 * @return
	 */
	private String processTextMessage(String fromUserName, String toUserName,
			String rsqContent) {
		String respMessage = "";
		String respContent;
		UserInfo userInfo = null;
		try {
			String token = sysConfigDAO.getAccessToken();
			userInfo = userDAO.subscribe(fromUserName, token);
		} catch (Exception e) {
			logger.error("subscribe and insert userinfo into DB", e);
		}
		if (userInfo == null) {
			logger.error("no subscriber info about " + fromUserName);
		}
		//
		// Employee emp = employeeDAO.getByOpenId(fromUserName);
		// if (emp == null) {
		// logger.info("please goto the menu 'zhitongche' at first.");
		// respContent = convertWelcomeMsg(fromUserName,
		// userInfo.getNickname());
		// respMessage = buildTextMsg(fromUserName, toUserName, respContent);
		// }
		// if (rsqContent.equalsIgnoreCase("m")) {
		// logger.debug("send out the job list");
		// respMessage = buildNewsMsg(fromUserName, toUserName,
		// PathEnum.recommend);
		// } else {
		// logger.debug("the user input message is text other than 'M': " +
		// rsqContent);
		// respMessage = buildTextMsg(fromUserName, toUserName,
		// SystemConfig.getProperties("SubscribeResponse"));
		//
		// // 客服接口回复 消息收到,尽快安排客服人员解答,
		// String token = sysConfigDAO.getAccessToken();
		// CustomerServiceMessageAPI.sendTextMsg(fromUserName,
		// SystemConfig.getProperties("SubscribeResponse"), token);
		//
		// // 转发消息给多客服
		// respMessage = buildCustomMsg(fromUserName, toUserName);
		// }

		respContent = convertWelcomeMsg(fromUserName, userInfo.getNickname());
		respMessage = buildTextMsg(fromUserName, toUserName, respContent);
		return respMessage;
	}

	private String convertWelcomeMsg(String openId, String nickname) {
		String respContent = "sucess";
		logger.debug(" welcom " + nickname + "openid is" + openId);
		String MSG = SystemConfig.getProperties("SubscribeMSG");
		// String MSG1 = SystemConfig.getProperties("SubscribeMSG_1");
		// String MSG2 = SystemConfig.getProperties("SubscribeMSG_2");
		// MSG1 = MSG1.replace("OPEN_ID", openId);

		respContent = "Hi, " + nickname + "," + MSG + "\n";// + MSG1 + "\n" +
															// MSG2;
		logger.debug(" welcome msg is " + respContent);
		return respContent;
	}

	private String buildBestPersionMsg(String fromUserName, String toUserName,
			String textMsg) {
		String respMessage = "";
		ResponseTextMessage rspMessage = new ResponseTextMessage();
		rspMessage.setToUserName(fromUserName);
		rspMessage.setFromUserName(toUserName);
		rspMessage.setCreateTime(new Date().getTime());
		rspMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
		rspMessage.setContent(textMsg);
		respMessage = MessageUtil.textMessageToXml(rspMessage);
		return respMessage;
	}

	private String buildTextMsg(String fromUserName, String toUserName,
			String textMsg) {
		String respMessage = "";
		ResponseTextMessage rspMessage = new ResponseTextMessage();
		rspMessage.setToUserName(fromUserName);
		rspMessage.setFromUserName(toUserName);
		rspMessage.setCreateTime(new Date().getTime());
		rspMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
		rspMessage.setContent(textMsg);
		respMessage = MessageUtil.textMessageToXml(rspMessage);
		return respMessage;
	}

	private String buildCustomMsg(String fromUserName, String toUserName) {
		String respMessage = "";
		ResponseNewsMessage newsMessage = new ResponseNewsMessage();
		newsMessage.setToUserName(fromUserName);
		newsMessage.setFromUserName(toUserName);
		newsMessage.setCreateTime(new Date().getTime());
		newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TRANSFER);

		respMessage = MessageUtil.newsMessageToXml(newsMessage);
		return respMessage;
	}

	private String buildNewsMsg(String fromUserName, String toUserName,
			PathEnum path) {

		String respMessage = "";
		ResponseNewsMessage newsMessage = new ResponseNewsMessage();
		newsMessage.setToUserName(fromUserName);
		newsMessage.setFromUserName(toUserName);
		newsMessage.setCreateTime(new Date().getTime());
		newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);

		List<Article> articles = new ArrayList<Article>();

		// platform, domain, path, start, end
		String openId = fromUserName;
		List<JobDesc> jobs = findJobs(path, openId);
		if (jobs == null || jobs.size() == 0) {
			logger.error("can not get the jobs list");
			// 暂时没有新的职位，如果继续点击菜单，将重新从第一页获取职位信息
			respMessage = buildTextMsg(fromUserName, toUserName,
					"暂时没有新的职位，如果继续点击菜单，将重新从第一页获取职位信息");
			return respMessage;
		}

		boolean isFirst = true;
		newsMessage.setArticleCount(jobs.size());
		for (JobDesc jd : jobs) {
			Article article = new Article();
			City city = cityDAO.getById(jd.getCityId());
			Company comp = companyDAO.getById(jd.getCompanyId());
			// article.setTitle(jd.getName() +" ["+jd.getCompanyName()+"] - "+
			// jd.getReward() + "元" );
			article.setTitle(comp.getName() + " " + jd.getName() + "( "
					+ city.getName() + " )" + " - " + jd.getReward() + "元");
			String domain = SystemConfig.getProperties("Domain");
			article.setUrl("http://" + domain + "/demo/wechat/candidate/"
					+ path.name() + "/jobdetail.page?id=" + jd.getId());
			if (isFirst) {

				article.setPicUrl("http://" + domain
						+ "/demo/resources/images/img15.jpg");
			} else {

				article.setPicUrl("http://" + domain
						+ "/demo/resources/images/img1.jpg");
			}
			isFirst = false;
			article.setDescription(jd.getDescription());
			articles.add(article);
		}
		newsMessage.setArticles(articles);
		respMessage = MessageUtil.newsMessageToXml(newsMessage);
		logger.debug("News Message is " + respMessage);
		return respMessage;
	}

	private List<JobDesc> findJobs(PathEnum path, String openId) {
		List<JobDesc> jobs = null;
		Employee emp = employeeDAO.getByOpenId(openId);
		if (emp == null) {
			logger.error("there is no employee with the openid " + openId);
			return null;
		}

		Integer offset = 0;
		int pageNum = 0;

		pageNum = persistentPage(openId, pageNum);
		offset = JobDescService.PAGE_SIZE * pageNum;
		logger.debug("pageNum is " + pageNum);
		Date todayDate = new Date();
		long today = todayDate.getTime();

		if (PathEnum.assistant.equals(path)) {
			// TODO: delete the interface is removed.
			jobs = jobService.searchRecommendJobs4Candidate(emp, offset, today);

		} else {
			jobs = jobService.searchRecommendJobs4Candidate(emp, offset, today);
		}
		logger.debug("jobs list is " + jobs);

		if (jobs == null || jobs.size() < JobDescService.PAGE_SIZE) {
			logger.info("the last page, reset the pagenumb");
			resetPage(openId, 0);
		}

		return jobs;
	}

	private int persistentPage(String openId, int pageNum) {
		int platformId = PlatformEnum.Candidate.getValue();
		int currentpageNum = pageNum;
		Page page = pageDAO.getByOpenId(openId, platformId);
		logger.debug("get page info" + page);
		if (page != null) {
			currentpageNum = page.getPageNum();
			page.setPageNum(currentpageNum + 1);
			pageDAO.update(page);
		} else {

			Page newPage = new Page();
			newPage.setOpenId(openId);
			newPage.setPageNum(1);
			newPage.setPlatformId(platformId);
			pageDAO.save(newPage);
		}
		return currentpageNum;
	}

	private int resetPage(String openId, int pageNum) {
		int platformId = PlatformEnum.Candidate.getValue();
		Page page = pageDAO.getByOpenId(openId, platformId);
		logger.debug("get page info" + page);
		if (page != null) {
			page.setPageNum(0);
			pageDAO.update(page);
		} else {
			Page newPage = new Page();
			newPage.setOpenId(openId);
			newPage.setPageNum(0);
			newPage.setPlatformId(platformId);
			pageDAO.save(newPage);
		}
		return pageNum;
	}
}
